#pragma once

#include "Const.h"
#include "Protocol.h"
#include <QPainter>
#include <QTcpSocket>
#include <QWidget>

// 游戏
class Game: public QTcpSocket {
    Q_OBJECT

    // 棋子类型
    private: enum Piece {
        NOTHING,    // 什么也没有
        BLACK,      // 黑棋
        WHITE       // 白棋
    };

    // 状态
    private: enum Status {
        END,            // 结束
        PLAYING,        // 自己下棋中
        RIVAL_PLAYING   // 对手下棋中
    };

    signals: void UM_GAME_OVER(GameOverReason);                 // 游戏结束事件
    signals: void UM_GAME_START(const char*);                   // 游戏开始事件
    signals: void UM_GET_FIND_USERS_RESULT(FindUsersResult*);   // 得到寻找用户结果事件
    signals: void UM_GET_INVITE_REQUEST(const char*);           // 得到挑战请求事件
    signals: void UM_GET_INVITE_RESULT(const char*, bool);      // 得到挑战结果事件
    signals: void UM_GET_LOGON_RESULT(bool);                    // 得到登录结果事件
    signals: void UM_RIVAL_QUIT_GAME(bool, const char*);        // 对手退出游戏事件

    private: QPixmap* mBitmap;          // 后台缓冲位图
    private: QBrush mBlackBrush;        // 黑色画刷
    private: QPainter mDrawer;          // 绘图者
    private: QWidget* mGameBoard;       // 游戏区域
    private: bool mIsBlack;             // 黑棋则为 true，白棋则为 false
    private: QPoint mLastPos;           // 上一次放置棋子的位置
    private: Piece mPieces[Const::GAME_BOARD_POINT_COUNT_V][Const::GAME_BOARD_POINT_COUNT_H];   // 所有棋子
    private: QString mRivalName;        // 对手的名字
    private: Status mStatus;            // 状态
    private: QString mUsername;         // 用户名
    private: QBrush mWhiteBrush;        // 白色画刷

    public: Game(QPixmap*, QWidget*);
    public: ~Game();
    public: void acceptInvite(const char*, bool);
    private: bool checkHorizontal();
    private: bool checkOblique1();
    private: bool checkOblique2();
    private: bool checkVertical();
    public: void defeat();
    private: void drawGameBoard();
    public: void findUsers();
    private: void gameOver(GameOverReason);
    private: void handleFindUsers(FindUsersResult*);
    private: void handleGameOver(GameOver*);
    private: void handleInviteRequest(InviteRequest*);
    private: void handleInviteResult(InviteResult*);
    private: void handleLogon(LogonResult*);
    private: void handlePutPiece(PutPiece*);
    private: void handleQuitGame(QuitGame*);
    public: void invite(const char*);
    private: bool isWon();
    public: void logon(const char*);
    public: void onGameBoardClicked(int x, int y);
    private: void onGetMessageFromServer(GomokuProtocol*);
    private slots: void onReceive();
    private: bool putPiece(bool, int, int);
    public: void restart();
    private: void sendData(GomokuProtocol*, qint64);
    public: void start(bool isBlack = true);
};
